<extend name="public/base2" />
<block name="head">
    <!-- BootstrapVue v2.15.0. -->
    <link rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css">
</block>
<block name="main-content">
    <div class="card">
        <!-- card-header -->
        <div class="card-header">
            <h3 class="card-title">编辑 - BootstrapVue</h3>
        </div>
        <!-- card-body -->
        <div class="card-body" id="edit">
            <b-alert 
                v-for="(msg, key) in alertMessage" 
                :key="key" 
                v-model="alert" 
                variant="danger" 
                dismissible fade
            >{{msg}}</b-alert>
            <b-form @submit.prevent.stop="onSubmit">
                <b-form-group
                    id="role-group"
                    label="角色组："
                    label-class="font-weight-normal"
                    label-for="role"
                    label-cols-xl="1"
                    label-cols="2"
                    :state="roleState"
                >
                    <b-row>
                        <b-col xl="6" lg="8">
                            <b-form-select 
                                name="role"
                                id="role" 
                                v-model="form.role.selected" 
                                type="select" 
                                :options="form.role.options"
                                value-field="id"
                                text-field="title"
                                required
                            ></b-form-select>
                        </b-col>
                        <b-col xl="6" lg="4">
                            <b-form-text text-variant="danger">*</b-form-text>
                        </b-col>
                    </b-row>
                </b-form-group>
                <b-form-group
                    id="username-group"
                    label="用户名："
                    label-class="font-weight-normal"
                    label-for="username"
                    label-cols-xl="1"
                    label-cols="2"
                >
                    <b-row>
                        <b-col xl="6" lg="8">
                            <b-input 
                                name="username" 
                                id="username" 
                                v-model="$v.form.username.$model" 
                                type="text"
                                placeholder="用户名"
                                :state="validateState('username')"
                                
                                trim
                            ></b-input>
                        </b-col>
                        <b-col xl="6" lg="4">
                            <b-form-text id="desc" text-variant="danger" class="w-75">
                                * 用户名长度在4到20个字符之间，并且用户名只能是字母、数字、下划线或它们的组合
                            </b-form-text>
                        </b-col>
                        <b-form-invalid-feedback id="username-required-feedback" :state="$v.form.username.required">
                            {{errorMsg.username.required}}
                        </b-form-invalid-feedback>
                        <b-form-invalid-feedback id="username-word-feedback" :state="$v.form.username.word">
                            {{errorMsg.username.word}}
                        </b-form-invalid-feedback>
                    </b-row>
                </b-form-group>
                <b-form-group
                    id="password-group"
                    label="密码："
                    label-class="font-weight-normal"
                    label-for="password"
                    label-cols-xl="1"
                    label-cols="2"
                >
                    <b-row>
                        <b-col xl="6" lg="8">
                            <b-input 
                                name="password"
                                id="password"
                                v-model="$v.form.password.$model"
                                type="password"
                                placeholder="密码"
                                :state="validateState('password')"
                                trim
                            ></b-input>
                        </b-col>
                        <b-col xl="6" lg="4">
                            <b-form-text text-variant="primary">密码应当不少于6个字符，且至少包含字母和数字</b-form-text>
                        </b-col>
                        <b-form-invalid-feedback id="password-password-feedback" :state="$v.form.password.password">
                            {{errorMsg.password.password}}
                        </b-form-invalid-feedback>
                    </b-row>
                </b-form-group>
                <b-form-group
                    id="avatar-group"
                    label="头像："
                    label-cols-xl="1"
                    label-cols="2"
                >
                    <b-row>
                        <b-col xl="6" lg="8">
                            <b-file 
                                name="avatar"
                                id="avatar"
                                v-model="$v.form.avatar.$model"
                                :state="validateState('avatar')"
                                :placeholder="avatarPlaceholder"
                                drop-placeholder="把头像拉到这里..."
                                accept="image/*"
                                browse-text="选择图像"
                            >
                                <template v-slot:file-name="{names}">
                                    <b-badge variant="dark">{{ names[0] }}</b-badge>
                                    <b-badge v-if="names.length > 1" variant="dark" class="ml-1">
                                        + {{ names.length - 1 }} More files
                                    </b-badge>
                                </template>
                            </b-file>
                        </b-col>
                        <b-col xl="6" lg="4">
                            <b-avatar id="popover-avatar" :src="avatarPreview" square></b-avatar>
                            <b-popover target="popover-avatar" triggers="hover">
                                <b-avatar :src="avatarPreview" square size="6rem"></b-avatar>
                            </b-popover>
                        </b-col>
                        <b-form-invalid-feedback id="avatar-size-feedback" :state="$v.form.avatar.size">
                            {{errorMsg.avatar.size}}
                        </b-form-invalid-feedback>
                        <b-form-invalid-feedback id="avatar-accept-feedback" :state="$v.form.avatar.accept">
                            {{errorMsg.avatar.accept}}
                        </b-form-invalid-feedback>
                    </b-row>
                </b-form-group>
                <b-form-group 
                    id="email-group"
                    label="Email地址："
                    label-class="font-weight-normal"
                    label-for="email"
                    label-cols-xl="1"
                    label-cols="2"
                    invalid-feedback="Email地址不能为空"
                >
                    <b-row>
                        <b-col xl="6" lg="8">
                            <b-input 
                                name="email" 
                                id="email" 
                                v-model="$v.form.email.$model" 
                                type="email" 
                                placeholder="邮箱"
                                :state="validateState('email')"
                            ></b-input>
                        </b-col>
                        <b-col xl="6" lg="4">
                            <b-form-text id="desc" text-variant="danger">*</b-form-text>
                        </b-col>
                        <b-form-invalid-feedback id="email-required-feedback" :state="$v.form.email.required">
                            {{errorMsg.email.required}}
                        </b-form-invalid-feedback>
                        <b-form-invalid-feedback id="email-email-feedback" :state="$v.form.email.email">
                            {{errorMsg.email.email}}
                        </b-form-invalid-feedback>
                    </b-row>
                </b-form-group>
                <b-form-group 
                    id="nickname-group"
                    label="昵称："
                    label-class="font-weight-normal"
                    label-for="nickname"
                    label-cols-xl="1"
                    label-cols="2"
                >
                    <b-row>
                        <b-col xl="6" lg="8">
                            <b-input 
                                name="nickname" 
                                id="nickname" 
                                v-model="$v.form.nickname.$model" 
                                type="text" 
                                placeholder="昵称"
                                :state="validateState('nickname')"
                                trim
                            ></b-input>
                        </b-col>
                        <b-col xl="6" lg="4">
                            <b-form-text id="desc" text-variant="primary">昵称长度在2到20个字符之间</b-form-text>
                        </b-col>
                        <b-form-invalid-feedback id="nickname-betweenLength-feedback" :state="$v.form.nickname.betweenLength">
                            {{errorMsg.nickname.betweenLength}}
                        </b-form-invalid-feedback>
                    </b-row>
                </b-form-group>
                <b-form-group 
                    id="status-group"
                    label="状态："
                    label-class="py-0"
                    label-cols-xl="1"
                    label-cols="2"
                    invalid-feedback="亲，你忘记选了"
                >
                    <b-row>
                        <b-col xl="6" lg="8">
                            <b-radio-group 
                                id="status" 
                                name="status"
                                v-model="$v.form.status.$model"
                                :options="statusOptions"
                                :state="validateState('status')"
                            ></b-radio-group>
                        </b-col>
                        <b-col xl="6" lg="4">
                            <b-form-text id="desc" text-variant="danger">*</b-form-text>
                        </b-col>
                        <b-form-invalid-feedback id="status-required-feedback" :state="$v.form.status.required">
                            {{errorMsg.status.required}}
                        </b-form-invalid-feedback>
                    </b-row>
                </b-form-group>
                <b-form-group 
                    id="submit-back-group"
                    label-cols-xl="1"
                    label-cols="2"
                >
                    <b-row>
                        <b-col xl="6" lg="8">
                            <b-btn type="submit" variant="info" class="mr-4 px-3">提 交</b-btn>
                            <b-btn class="px-3" @click="jsBack">返 回</b-btn>
                        </b-col>
                    </b-row>
                </b-form-group>
            </b-form>
            <b-modal
                id="bv-modal-form" 
                ok-title="确定"
                title-class="text-danger"
                no-close-on-backdrop
                ok-only
                centered
            >
                <template v-slot:modal-title>
                    <b-icon icon="emoji-frown"></b-icon> 出错啦
                </template>
                <p v-for="(msg, key) in errorMsgList" :key="key">{{msg}}</p>
            </b-modal>
            <b-overlay
                :show="busy" 
                z-index=1050
                no-wrap
                fixed
            >
                <template v-slot:overlay>
                    <div id="progress" v-if="processing">
                        <b-icon icon="arrow-clockwise" animation="spin" font-scale="7.5"></b-icon>
                        <b-progress :value="progress" class="position-absolute w-50" show-progress animated></b-progress>
                    </div>
                    <b-toast
                        v-else
                        id="sure-toast" 
                        toast-class="px-5" 
                        header-class="d-none"
                        body-class="text-center py-5"
                        v-model="sureToastShow"
                        no-auto-hide 
                        static
                    >
                        <h4 class="mb-4 pb-2">你确定修改吗？</h4>
                        <p class="mb-0">
                            <b-btn variant="outline-danger" class="px-3" @click="(sureToastShow = false) || (busy = false)">取消</b-btn>
                            <b-btn  variant="outline-success" class="ml-5 px-3"  @click="onOk">确定</b-btn>
                        </p>
                    </b-toast>
                </template>
            </b-overlay>
        </div>
    </div>
</block>
<block name="footer-script">
    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script>window.jQuery || document.write('<script src="__ADMINLTE__/plugins/jquery/jquery.min.js"><\/script>')</script>
   <!-- 加载polyfills以支持旧的浏览器 -->
    <script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
    <!-- AdminLTE App -->
    <script src="__ADMINLTE__/dist/js/adminlte.min.js"></script>
    <!-- Popper -->
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/inputmask@5.0.3/dist/inputmask.min.js"></script>
    <!-- Vue最新版 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- PortalVue - 一个Vue组件，用于在DOM中的任何位置呈现组件的模板-->
    <script src="http://unpkg.com/portal-vue"></script>
    <!-- BootstrapVue最新版 -->
    <script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
    <!-- 加载以下内容以获得BootstrapVueIcons支持 -->
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
    <!-- Vuelidate 最新版 -->
    <script src="https://unpkg.com/vuelidate@latest/dist/vuelidate.min.js"></script>
    <!-- Vuelidate的内置验证器 最新版 -->
    <script src="https://unpkg.com/vuelidate@latest/dist/validators.min.js"></script>
    <!-- axios(类似Ajax) -->
    <js href="https://unpkg.com/axios@0.19.2/dist/axios.min.js" />
    <!-- App JS -->
    <script src="__STATIC__/js/app.js"></script>

    <script>
        // 为Vue全局安装vuelidate验证器插件
        Vue.use(window.vuelidate.default)
        const { required, minLength, maxLength, helpers, email, and } = window.validators
        /**
         * 单词验证器
         * 
         * 匹配包括下划线的任何单词字符，等价于[A-Za-z0-9_]，
         * operator是数字时：匹配number到operator之间长度的单词字符串，
         * operator是'>'操作符时：匹配至少number长度的单词字符串，
         * operator是空时：匹配number长度的单词字符串，
         * 
         * @return bool
         **/
        const word = (number, operator) => {
            return (value) => {
                let patt;
                switch (true) {
                    case null == operator || 'undefined' == typeof(operator) || '' == operator || '=' == operator:
                        patt =  number + '';
                        break;
                    case '>' == operator:
                        patt = number + ',';
                        break;
                    case !isNaN(operator) && isFinite(operator) && operator == Math.floor(operator):
                        patt = number + ',' + operator;
                        break;
                    default: 
                        return false;
                }
                
                return helpers.req(value) && new RegExp("^\\w{" + patt + "}$").test(value)
            }
        }

        var message = {
            username: {
                required: "用户名不能为空",
                word: "请输入有效的用户名"
            },
            password: {
                password: "请确保密码不少于6个字符，且至少包含字母和数字"
            },
            avatar: {
                size: "文件太大了, 最大不能超过" + ('{$avatar_maxsize}' / 1024 / 1024) + 'M',
                accept: "不能上传非图像文件"
            },
            email: {
                required: "Email地址不能为空",
                email: "Email地址格式不正确"
            },
            nickname: {
                betweenLength: "昵称长度错误"
            },
            status: {
                required: "状态不能为空"
            }
        }
      
        var vm = new Vue({
                el: '#edit',
                data: {
                    form: {
                        role: { // 用这种数据形式生成的下拉选择不大好，应该是像下面的status
                            selected: '{$user_editing.group_id}',
                            options: JSON.parse('{$role_options}')
                        },
                        username: '{$user_editing.admin_name}',
                        password: '',
                        email: '{$user_editing.admin_email}',
                        avatar: null,
                        nickname: '{$user_editing.admin_nickname}',
                        status: '{$user_editing.status}'
                    },
                    statusOptions: [
                        { html: '<span class="font-weight-normal">显示</span>', value: 1 },
                        { html: '<span class="font-weight-normal">隐藏</span>', value: 0 }
                    ],
                    avatarPreview: '{$user_editing.icon}',
                    errorMsg: message,
                    errorMsgList: [],
                    busy: false,
                    sureToastShow: false,
                    processing: false,
                    progress: 0,
                    alert: false,
                    alertMessage: []
                },
                validations: {
                    form: {
                        username: {
                            required,
                            word: word(4, 20)
                        },
                        password: {
                            // 匹配至少包含字母和数字的6个以上的字符串
                            password: helpers.regex('password', /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z~!@#$%^&*()><,.?\-_=+/|;:'"]{6,}$/)
                        },
                        avatar: {
                            size() {
                                if (null === this.$v.form.avatar.$model)
                                    return true;
                                else
                                    // 验证头像的上传大小
                                    return this.$v.form.avatar.$model.size < '{$avatar_maxsize}';
                            },
                            accept() {
                                if (null === this.$v.form.avatar.$model)
                                    return true;
                                else
                                    // 验证头像的文件类型
                                    return this.$v.form.avatar.$model.type.indexOf('image/') !== -1;
                            }
                        },
                        email: {
                            required,
                            email
                        },
                        nickname: {
                            betweenLength: and( minLength(2), maxLength(20) )
                        },
                        status: {
                            required
                        }
                    }
                },
                computed: {
                    roleState() {
                        this.form.role.options.forEach((item, index) => {
                            if ('{$user.group_id}' == 1) {
                                // 如果当前编辑用户已经是属于超管组了，则不能改角色组。(总不能把超管变普管吧)
                                if (1 == '{$user_editing.group_id}') 
                                    this.form.role.options[index].disabled = true;
                            } else {
                                // 非超级管理员不能更改角色组
                                this.form.role.options[index].disabled = true;
                            }
                        });                        
                    },
                    statusState() {
                        let selected = false;
                        this.statusOptions.forEach(item => {
                            (item.value == this.status) && (selected = true)
                        });
                        // 未选择提示，选择则不提示
                        if (selected)
                            return null;
                        else
                            return false;
                    },
                    avatarPlaceholder() {
                        return this.avatarPreview || '选择一个头像文件或把它拉到这里';
                    }
                },
                watch: {},
                methods: {
                    // 返回字段的验证状态
                    validateState(name) {
                        const { $dirty, $error } = this.$v.form[name];
                        // 如果在v-model里直接写入$v..$model时，$dirty会自动设置为true，
                        // 表示字段被用户至少触摸了一次，意味着消息将显示给最终用户
                        if ($dirty) 
                        {
                            // 表单控件发生更改或输入后返回验证字段状态
                            return !$error
                        } else {
                            // if (name == 'status') 
                            // {
                            //     // status控件还没发生更改时，就验证其状态
                            //     return this.statusState;
                            // }
                            return null;
                        }
                    },
                    jsBack() {
                        history.back(-1);
                    },
                    onSubmit(evt) {
                        // 手动触摸，验证表单
                        this.$v.form.$touch();
                        // 收集表单错误提示信息
                        if (this.$v.form.$anyError) {
                            let list = [];
                            for (let key in this.errorMsg) {
                                if (this.$v.form[key].$anyError) {
                                    for (let kk in this.errorMsg[key]) {
                                        if (!this.$v.form[key][kk])
                                            list.push(this.errorMsg[key][kk]);
                                    }
                                }
                            }
                            this.errorMsgList = list;
                            this.$bvModal.show('bv-modal-form');
                        } else {
                            // 表单正确提交时，弹出覆盖层，再弹出确认框
                            this.busy = this.sureToastShow = true;
                            this.alert = false;
                            this.progress = 0;
                        }
                    },
                    onOk() {
                        this.processing = true;
                        var formObj = new FormData();
                        formObj.append('avatar', this.form.avatar)
                        formObj.append('pk', '{:input("id")}')
                        formObj.append('name', 'all')
                        formObj.append('__token__', '{$Request.token}')
                        formObj.append('_method', 'PUT')
                        formObj.append('value', JSON.stringify(this.form))
                        let vm = this;
                        axios.post("{:url('/"+CONTROLLER+"/all')}?_ajax=1", formObj, {
                            onUploadProgress(progressEvent) {
                                // 不知为何，没有选择文件lengthComputable也会是true
                                // 所以先暂时再加个条件
                                if (progressEvent.lengthComputable && vm.form.avatar)
                                {
                                    vm.progress = ((progressEvent.loaded * 100) / progressEvent.total) . toFixed(2);
                                }
                            }
                        })
                        .then(response => {
                            if (1 === response.data.code)
                            {
                                // 将加载进度条的进度信息更新为100%，以保证进度显示确实达到了100%（以防在上传过程中出现粒度误差）
                                vm.progress = 100;
                                if (response.url) {
                                    window.location.href = response.data.url;
                                }
                                // 编辑成功返回管理员列表页
                                history.back(-1);
                            } else if (0 === response.data.code) {
                                vm.alertMessage = response.data.data;
                                vm.alert = true;
                                vm.busy = vm.sureToastShow = vm.processing = false;
                            }
                        })
                        .catch(error => {
                            vm.alertMessage.push(adminEditingError(error));
                            vm.alert = true;
                            vm.busy = vm.sureToastShow = vm.processing = false;
                        })
                    }
                }
            })
    </script>
</block>